package com.webber.demo.common.utils;


import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.servlet.http.HttpServletRequest;
import com.webber.demo.entity.UploadResDto;







import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;

import org.apache.log4j.Logger;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;


/**
 * 文件上传工具类
 * 
 * @author Administrator
 *
 */
public class FileUploadUtil {
	private static final Logger log = Logger.getLogger(FileUploadUtil.class);

	private static final String REALNAME = "realName";// 真实名称

	private static final String STORENAME = "storeName";// 存储名称

	private static final String SIZE = "size";// 大小

	private static final String SUFFIX = "suffix";// 后缀

	private static final String CREATETIME = "createTime";// 创建时间

	private static final String CONTENTTYPE = "contentType";// 类型

	/**
	 * 处理压缩文件的名字
	 * 
	 * @param name
	 * @return
	 */
	private static String zipName(String name) {
		String prefix = "";
		if (name.indexOf(".") != -1) {
			prefix = name.substring(0, name.lastIndexOf("."));
		} else {
			prefix = name;
		}
		return prefix + ".zip";
	}

	/**
	 * 上传，描述如何获取项目根路径，创建文件夹，通过multipart来获取文件夹的正式名字
	 * 
	 * @param request
	 * @param uploadPath
	 * @param needZip
	 * @return
	 * @throws Exception
	 */
	public static List<Map<String, Object>> upload(HttpServletRequest request,String uploadPath, boolean needZip) throws Exception  {
		List<Map<String, Object>> result = new ArrayList();
		// 获取项目根路径
		String path = request.getSession().getServletContext().getRealPath(uploadPath);

		MultipartHttpServletRequest mRequest = (MultipartHttpServletRequest) request;
		String uploadDir = path;
		File file = new File(uploadDir);
		if (!file.exists()) {
			file.mkdirs();
		}
		log.debug("-----------------------------" + uploadDir);
		String fileName = null;

		String regEx = "[\\u4e00-\\u9fa5]";
		Pattern p = Pattern.compile(regEx);
		log.debug("-------------------fileMap.entrySet()----------"+ mRequest.getFileNames());

		for (Iterator<String> it = mRequest.getFileNames(); it.hasNext();) {
			log.debug("---------------------------eter--");
			String key = (String) it.next();
			MultipartFile mFile = mRequest.getFile(key);
			fileName = mFile.getOriginalFilename();
			String fileExt = FileUtil.getFileExt(fileName).toUpperCase();
			log.debug("----------fileName----------------eter--" + fileName);
			Map<String, Object> map = new HashMap();
			if (!StringUtil.isBlank(fileName)) {
				Matcher m = p.matcher(fileName);
				if (m.find()) {
					fileName = StringUtil.cleanSpecificSymbol(CnToSpell.getPinYin(fileName)) ;
					map.put("fileName", fileName);
				}else{
					fileName = StringUtil.cleanSpecificSymbol(fileName);
				}
				fileName=fileName.replace(fileExt, "").trim().replace(fileExt.toLowerCase(), "").trim()+"."+fileExt;
				if ((fileExt == null) || (fileExt.length() == 0)) {
					throw new Exception("文件后缀不能为空！");
				}

				if ((!"MP3".equals(fileExt)) && (".MP4.mp4".indexOf(fileExt)!=-1)
						&& (!"PNG".equals(fileExt)) && (!"DOC".equals(fileExt))
						&& ("DOCX".equals(fileExt)) && ("XLS".equals(fileExt))
						&& ("XLSX".equals(fileExt)) && ("PPT".equals(fileExt))
						&& ("RAR".equals(fileExt)) && ("ZIP".equals(fileExt))
						&& ("TXT".equals(fileExt)) && ("PDF".equals(fileExt))) {
					throw new Exception("文件格式不正确！");
				}
				if (needZip) {
					 
					String storeName = fileName;

					String noZipName = uploadDir + "/" + storeName;
					String zipName = zipName(noZipName);

					ZipOutputStream outputStream = null;
					try {
						outputStream = new ZipOutputStream(	new BufferedOutputStream(new FileOutputStream(zipName)));
						outputStream.putNextEntry(new ZipEntry(fileName));
						FileCopyUtils.copy(mFile.getInputStream(), outputStream);
					}catch (IOException e) {
						throw new Exception("文件上传失败！");
					}finally{
						if(outputStream!=null){
							try {
								outputStream.flush();
							} catch (IOException e) {
								e.printStackTrace();
							}
							try {
								outputStream.close();
							} catch (IOException e) {
								e.printStackTrace();
							}
						}
					}
					
					map.put("realName", zipName(fileName));
					// map.put("storeName", zipName(storeName));
					map.put("size", Long.valueOf(new File(zipName).length()));
					map.put("suffix", "zip");
					map.put("createTime", new Date());
					map.put("duration", "0");
				} else {
					log.debug("-------------------+不需要要素-------------------");
					//String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());
					 
					String noZipName = uploadDir + "/" + fileName;
					String realName = uploadPath + "/" + fileName;// 相对路径存储在数据库中
					BufferedOutputStream outputStream = null;
					try {
						outputStream = new BufferedOutputStream(new FileOutputStream(noZipName));
						FileCopyUtils.copy(mFile.getInputStream(), outputStream);
					} catch (IOException e) {
						throw new Exception("文件上传失败！");
					}finally{
						if(outputStream!=null){
							try {
								outputStream.flush();
							} catch (IOException e) {
								e.printStackTrace();
							}
							try {
								outputStream.close();
							} catch (IOException e) {
								e.printStackTrace();
							}
						}
					}
					long duration = 0;//时长
					if(("MP3".equals(fileExt)) || ("MP4".equals(fileExt)))
					{
						duration = getVideoFileInfo(noZipName);
					}
					map.put("realName", realName);
					// map.put("storeName", noZipName);
					map.put("size", Long.valueOf(new File(noZipName).length()));
					map.put("suffix", fileExt);
					map.put("createTime", new Date());
					map.put("duration", Long.valueOf(duration));
				}
			} else {
				return new ArrayList();
			}
			result.add(map);
		}
		return result;
	}
	
	
	public static List<UploadResDto> uploadFile(HttpServletRequest request,String uploadPath,boolean needZip) throws Exception  {
		List<UploadResDto> result = new ArrayList<UploadResDto>();
		// 获取项目根路径
		String path = request.getSession().getServletContext().getRealPath(uploadPath);
		MultipartHttpServletRequest mRequest = (MultipartHttpServletRequest) request;
		String uploadDir = path;
		File file = new File(uploadDir);
		if (!file.exists()) {
			file.mkdirs();
		}
		String fileName = null;

		String regEx = "[\\u4e00-\\u9fa5]";
		Pattern p = Pattern.compile(regEx);

		for (Iterator<String> it = mRequest.getFileNames(); it.hasNext();) {
			String key = (String) it.next();
			MultipartFile mFile = mRequest.getFile(key);
			fileName = mFile.getOriginalFilename();
			log.debug("----------fileName----------------eter--" + fileName);
			UploadResDto ur = new UploadResDto(); 
			if (!StringUtil.isBlank(fileName)) {
				Matcher m = p.matcher(fileName);
				String fileExt = FileUtil.getFileExt(fileName).toUpperCase();
				if (m.find()) {
					fileName = StringUtil.cleanSpecificSymbol(CnToSpell.getPinYin(fileName)) ;
					ur.setFielName(fileName);
					fileName = StringUtil.cleanSpecificSymbol(fileName);
				}else{
					fileName = StringUtil.cleanSpecificSymbol(fileName);
				}
				fileName=fileName.replace(fileExt, "").trim().replace(fileExt.toLowerCase(), "").trim()+"."+fileExt;
				ur.setFielName(fileName);
				
				if ((fileExt == null) || (fileExt.length() == 0)) {
					throw new Exception("文件后缀不能为空！");
				}
				if ((!"MP3".equals(fileExt)) && (".MP4.mp4".indexOf(fileExt)!=-1)
						&& (!"PNG".equals(fileExt)) && (!"DOC".equals(fileExt))
						&& ("DOCX".equals(fileExt)) && ("XLS".equals(fileExt))
						&& ("XLSX".equals(fileExt)) && ("PPT".equals(fileExt))
						&& ("RAR".equals(fileExt)) && ("ZIP".equals(fileExt))
						&& ("TXT".equals(fileExt)) && ("PDF".equals(fileExt))) {
					throw new Exception("文件格式不正确！");
				}
				//String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());
				String noZipName =uploadDir + "/" +fileName;
				String realName =uploadPath + "/" + fileName;// 相对路径存储在数据库中
				BufferedOutputStream outputStream = null;
				try {
					outputStream = new BufferedOutputStream(new FileOutputStream(noZipName));
					FileCopyUtils.copy(mFile.getInputStream(), outputStream);
					ur.setSuccess(true);
				} catch (IOException e) {
					throw new Exception("文件上传失败！");
				}finally{
					if(outputStream!=null){
						try {
							outputStream.flush();
						} catch (IOException e) {
							e.printStackTrace();
						}
						try {
							outputStream.close();
						} catch (IOException e) {
							e.printStackTrace();
						}
					}
				}
				long duration = getVideoFileInfo(noZipName);
				ur.setUploadpath(realName);
				ur.setFileSize(Long.valueOf(new File(noZipName).length()));
				ur.setFileType(fileExt);
				ur.setMediaTime(Long.valueOf(duration));
				// map.put("storeName", noZipName);
			
			} 
			ur.setCreateTime(DateUtil.getTime());
			result.add(ur);
		}
		return result;
	}
	
	/**
	 * 
	 * <p>Title: uploadFileChunks</p>
	 * <p>Description: 分片上传文件</p>
	 * @param request
	 * @param uploadPath//上传路径
	 * @param needZip是否需要解压缩
	 * @return
	 * @throws Exception
	 * @author JobsZhang
	 * @date 2017年10月17日 下午3:41:56
	 */
	public static List<UploadResDto> uploadFileChunks(HttpServletRequest request,String uploadPath, String fileMd5,String chunk,boolean needZip) throws Exception  {
		List<UploadResDto> result = new ArrayList<UploadResDto>();
		uploadPath=uploadPath+"/"+fileMd5;
		// 获取项目根路径
		String path = request.getSession().getServletContext().getRealPath(uploadPath);
		MultipartHttpServletRequest mRequest = (MultipartHttpServletRequest) request;
		String uploadDir = path;
		File file = new File(uploadDir);
		if (!file.exists()) {
			file.mkdirs();
		}
		String fileName = null;

		String regEx = "[\\u4e00-\\u9fa5]";
		Pattern p = Pattern.compile(regEx);

		for (Iterator<String> it = mRequest.getFileNames(); it.hasNext();) {
			String key = (String) it.next();
			MultipartFile mFile = mRequest.getFile(key);
			fileName = mFile.getOriginalFilename();
			log.debug("----------fileName----------------eter--" + fileName);
			UploadResDto ur = new UploadResDto(); 
			if (!StringUtil.isBlank(fileName)) {
				Matcher m = p.matcher(fileName);
				String fileExt = FileUtil.getFileExt(fileName).toUpperCase();
				if (m.find()) {
					fileName = StringUtil.cleanSpecificSymbol(CnToSpell.getPinYin(fileName)) ;
					ur.setFielName(fileName);
					fileName = StringUtil.cleanSpecificSymbol(fileName);
				}else{
					fileName = StringUtil.cleanSpecificSymbol(fileName);
				}
				fileName=fileName.replace(fileExt, "").trim().replace(fileExt.toLowerCase(), "").trim()+"."+fileExt;
				ur.setFielName(fileName);
				
				if ((fileExt == null) || (fileExt.length() == 0)) {
					throw new Exception("文件后缀不能为空！");
				}
				if ((!"MP3".equals(fileExt)) && (".MP4.mp4".indexOf(fileExt)!=-1)
						&& (!"PNG".equals(fileExt)) && (!"DOC".equals(fileExt))
						&& ("DOCX".equals(fileExt)) && ("XLS".equals(fileExt))
						&& ("XLSX".equals(fileExt)) && ("PPT".equals(fileExt))
						&& ("RAR".equals(fileExt)) && ("ZIP".equals(fileExt))
						&& ("TXT".equals(fileExt)) && ("PDF".equals(fileExt))) {
					throw new Exception("文件格式不正确！");
				}
				//String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());
				String noZipName =uploadDir + "/" +chunk;
				String realName =uploadPath + "/" + fileName;// 相对路径存储在数据库中
				BufferedOutputStream outputStream = null;
				try {
					outputStream = new BufferedOutputStream(new FileOutputStream(noZipName));
					FileCopyUtils.copy(mFile.getInputStream(), outputStream);
					ur.setSuccess(true);
				} catch (IOException e) {
					throw new Exception("文件上传失败！");
				}finally{
					if(outputStream!=null){
						try {
							outputStream.flush();
						} catch (IOException e) {
							e.printStackTrace();
						}
						try {
							outputStream.close();
						} catch (IOException e) {
							e.printStackTrace();
						}
					}
				}
				long duration = 0;//时长
				ur.setUploadpath(realName);
				ur.setFileSize(Long.valueOf(new File(noZipName).length()));
				ur.setFileType(fileExt);
				ur.setMediaTime(Long.valueOf(duration));
				// map.put("storeName", noZipName);
			
			} 
			ur.setCreateTime(DateUtil.getTime());
			result.add(ur);
		}
		return result;
	}
	/**
	 * 图片上传，非课件上传使用
	 * 上传的图片会被重命名
	 * 格式：/YYYYMMDD/
	 *
	 * @param request
	 * @param uploadPath
	 * @param needZip
	 * @return
	 * @throws Exception
	 */
	public static List<Map<String, Object>> uploadImg(HttpServletRequest request, String uploadPath, boolean needZip) throws Exception  {
		List<Map<String, Object>> result = new ArrayList();
		// 获取项目根路径
		String path = request.getSession().getServletContext().getRealPath(uploadPath);

		MultipartHttpServletRequest mRequest = (MultipartHttpServletRequest) request;
		String uploadDir = path;
		File file = new File(uploadDir);

		if (!file.exists()) {
			file.mkdirs();
		}
		log.debug("-----------------------------" + uploadDir);
		String fileName = null;
		String app_fileName = null;//app端图片

		String regEx = "[\\u4e00-\\u9fa5]";
		Pattern p = Pattern.compile(regEx);
		log.debug("-------------------fileMap.entrySet()----------"
				+ mRequest.getFileNames());

		for (Iterator<String> it = mRequest.getFileNames(); it.hasNext();) {
			log.debug("---------------------------eter--");
			String key = (String) it.next();
			MultipartFile mFile = mRequest.getFile(key);
			fileName = mFile.getOriginalFilename();
			log.debug("----------fileName----------------eter--" + fileName);
			Map<String, Object> map = new HashMap();
			if (!StringUtil.isBlank(fileName)) {
				Matcher m = p.matcher(fileName);
				String fileExt = FileUtil.getFileExt(fileName).toUpperCase();
				if (m.find()) {
					fileName =  StringUtil.cleanSpecificSymbol(CnToSpell.getPinYin(fileName));
					map.put("fileName", fileName);
				}else{
					fileName = StringUtil.cleanSpecificSymbol(fileName);
				}
				fileName=fileName.replace(fileExt, "").trim().replace(fileExt.toLowerCase(), "").trim()+"."+fileExt;
				if ((fileExt == null) || (fileExt.length() == 0)) {
					throw new Exception("文件后缀不能为空！");
				}

				if ((!"PNG".equals(fileExt)) && (!"JPG".equals(fileExt)) && (!"JPEG".equals(fileExt)) && (!"GIF".equals(fileExt))&&(!"BMP".equals(fileExt))) {
					throw new Exception("文件格式不正确！");
				}
				if (needZip) {
					fileName = new Date().getTime() + fileName.substring(fileName.lastIndexOf("."));//文件重命名
					String storeName = fileName;

					String noZipName = uploadDir + "/" + storeName;
					String zipName = zipName(noZipName);

					ZipOutputStream outputStream = null;
					try {
						outputStream = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipName)));
						outputStream.putNextEntry(new ZipEntry(fileName));
						FileCopyUtils.copy(mFile.getInputStream(), outputStream);
					}catch (IOException e) {
						throw new Exception("文件上传失败！");
					}finally{
						if(outputStream!=null){
							try {
								outputStream.flush();
							} catch (IOException e) {
								e.printStackTrace();
							}
							try {
								outputStream.close();
							} catch (IOException e) {
								e.printStackTrace();
							}
						}
					}

					map.put("realName", zipName(fileName));
					// map.put("storeName", zipName(storeName));
					map.put("size", Long.valueOf(new File(zipName).length()));
					map.put("suffix", "zip");
					map.put("createTime", new Date());
					map.put("duration", "0");
				} else {
					log.debug("-------------------+不需要压缩-------------------");
					fileName = new Date().getTime() + fileName.substring(fileName.lastIndexOf("."));//文件重命名
					app_fileName = "app_" + fileName;//app端图片

					String noZipName = uploadDir + "/" + fileName;
					String app_noZipName = uploadDir + "/" + app_fileName;//app端图片

					String realName = uploadPath + "/" + fileName;// 相对路径存储在数据库中
					String app_realName = uploadPath + "/" + app_fileName;// 相对路径存储在数据库中
					BufferedOutputStream outputStream = null;
					BufferedOutputStream app_outputStream = null;//app端图片
					try {
						outputStream = new BufferedOutputStream(new FileOutputStream(noZipName));
						FileCopyUtils.copy(mFile.getInputStream(), outputStream);
						outputStream = new BufferedOutputStream(new FileOutputStream(app_noZipName));//app端图片
						FileCopyUtils.copy(mFile.getInputStream(), outputStream);//app端图片

						//app图片压缩
						ImageUtil imageUtil = new ImageUtil();
						imageUtil.Converting(app_noZipName);

					} catch (IOException e) {
						throw new Exception("文件上传失败！");
					}finally{
						if(outputStream!=null){
							try {
								outputStream.flush();
							} catch (IOException e) {
								e.printStackTrace();
							}
							try {
								outputStream.close();
							} catch (IOException e) {
								e.printStackTrace();
							}
						}
					}
					long duration = 0;
					if(("MP3".equals(fileExt)) || ("MP4".equals(fileExt)))
					{
						duration = getVideoFileInfo(noZipName);
					}
					map.put("realName", realName);
					map.put("app_realName", app_realName);
					// map.put("storeName", noZipName);
					map.put("size", Long.valueOf(new File(noZipName).length()));
					map.put("suffix", fileExt);
					map.put("createTime", new Date());
					map.put("duration", Long.valueOf(duration));
				}
			} else {
				return new ArrayList();
			}
			result.add(map);
		}
		return result;
	}
	
	/**
	 * 获取音视频的播放时长
	 * 
	 * @param filepath
	 * @return
	 */
	public static long getVideoFileInfo(String filepath) {

		/*File source = new File(filepath);
		Encoder encoder = new Encoder();
		try {
			MultimediaInfo m = encoder.getInfo(source);
			return m.getDuration();

		} catch (Exception e) {
			e.printStackTrace();
		}*/
		return 0;
	}

	public static String getRealname() {
		return "realName";
	}

	public static String getStorename() {
		return "storeName";
	}

	public static String getSize() {
		return "size";
	}

	public static String getSuffix() {
		return "suffix";
	}

	public static String getCreatetime() {
		return "createTime";
	}

	public static String getContenttype() {
		return "contentType";
	}
	
	public static String getDuration(){
		return "duration";
	}

	@SuppressWarnings("resource")
	public static UploadResDto mergeChunks(HttpServletRequest request,String uploadPath,String fileMd5,String fileName) {
		log.debug("----------开始合并文件----------------eter--" );
		UploadResDto ur = new UploadResDto();
		String path = request.getSession().getServletContext().getRealPath(uploadPath);
		String regEx = "[\\u4e00-\\u9fa5]";
		Pattern p = Pattern.compile(regEx);
		Matcher m = p.matcher(fileName);
		String fileExt = FileUtil.getFileExt(fileName).toUpperCase();
		if (m.find()) {
			try {
				fileName = StringUtil.cleanSpecificSymbol(CnToSpell.getPinYin(fileName)) ;
			} catch (BadHanyuPinyinOutputFormatCombination e) {
				e.printStackTrace();
			}
			ur.setFielName(fileName);
		}else{
			fileName = StringUtil.cleanSpecificSymbol(fileName);
		}
		
		
		File f = new File(path+"/"+fileMd5);
		File[] fileArray = f.listFiles(new FileFilter() {
			// 排除目录，只要文件
			public boolean accept(File pathname) {
				if (pathname.isDirectory()) {
					return false;
				}
				return true;
			}
		});
		// 转成集合，便于排序
		List<File> fileList = new ArrayList<File>(Arrays.asList(fileArray));
		// 从小到大排序
		Collections.sort(fileList, new Comparator<File>() {
			public int compare(File o1, File o2) {
				if (Integer.parseInt(o1.getName()) < Integer.parseInt(o2.getName())) {
					return -1;
				}
				return 1;
			}

		});
		File outputFile = new File(path + "/" + fileName.replace(fileExt, "").trim().replace(fileExt.toLowerCase(), "").trim()+"."+fileExt);
		// 创建文件
		try {
			outputFile.createNewFile();
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		// 输出流
		FileChannel outChannel = null;
		try {
			
			
			outChannel = new FileOutputStream(outputFile).getChannel();
			// 合并
			FileChannel inChannel;
			for (File file : fileList) {
				inChannel = new FileInputStream(file).getChannel();
				inChannel.transferTo(0, inChannel.size(), outChannel);
				inChannel.close();
				// 删除分片
				file.delete();
			}
			ur.setSuccess(true);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (outChannel != null) {
				// 关闭流
				try {
					outChannel.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			// 清除文件夹
			File tempFile = new File(path + "/" + fileMd5);
			if (tempFile.isDirectory() && tempFile.exists()) {
				tempFile.delete();
			}
			String filePath=path + "/" + fileName.replace(fileExt, "").trim().replace(fileExt.toLowerCase(), "").trim()+"."+fileExt;
			File fil = new File(filePath);
			if(fil.exists()){
				log.debug("================="+filePath);
				Long duration = getVideoFileInfo(filePath);
				log.debug("================="+path);
				ur.setRealPath(filePath);
				ur.setFielName(fileName);
				ur.setUploadpath(uploadPath+"/"+fileName.replace(fileExt, "").trim().replace(fileExt.toLowerCase(), "").trim()+"."+fileExt);
				ur.setFileType(fileExt);
				ur.setMediaTime(duration);
				ur.setSuccess(true);
				ur.setFileSize(fil.length());
			}
			
		}
		return ur;
	}
}
